package br.gov.ibama.client.servico;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.grid.ListGrid;

public class ServicoOperacoesCRUD implements OperacoesCRUD, EventosOperacoes {
	private DynamicForm formulario;
	private String operationID;
	private String tituloMensagem;
	private String mensagem;
	private String nomeDataSouce;

	private EventosOperacoesHandler listener;

	private BooleanCallback callBackSalvar = null;


	private final class CallBackSalvar implements DSCallback {
		public void execute(DSResponse response, Object rawData,
				DSRequest request) {
			if (RPCResponse.STATUS_SUCCESS == response.getStatus()) {
				if (tituloMensagem != null && !tituloMensagem.equals("")
						&& mensagem != null && !mensagem.equals("")) {
					SC.say(tituloMensagem, mensagem, new BooleanCallback() {
						public void execute(Boolean value) {
							//Window.Location.reload();
							if (listener != null) {
								listener.handleSaveOperation();
							}
						}
					});
				}

				if (callBackSalvar != null) {
					callBackSalvar.execute(true);
				}
			} else if (RPCResponse.STATUS_VALIDATION_ERROR == response
					.getStatus()) {
				formulario.setErrors(response.getErrors(), true);
				SC.say("Existem erros de validação, por favor verificar os dados informados");
			} else if (RPCResponse.STATUS_FAILURE == response.getStatus()) {
				SC.say("Falha ao executar a operação.");
			}
		}
	}

	private final class CallBackFetch implements DSCallback {
		public void execute(DSResponse response, Object rawData,
				DSRequest request) {
			if (RPCResponse.STATUS_SUCCESS == response.getStatus()) {
				if (listener != null) {
					listener.handleFetchOperation();
				}
			}
		}
	}

	private final class CallBackApagar implements DSCallback {
		public void execute(DSResponse response, Object rawData,
				DSRequest request) {
			if (RPCResponse.STATUS_SUCCESS == response.getStatus()) {
				SC.say("Dados apagados com sucesso");

				if (listener != null) {
					listener.handleDeleteOperation();
				}
			} else if (RPCResponse.STATUS_FAILURE == response.getStatus()) {
				SC.say("Erro ao apagar dados");
			}
		}
	}

	private final class CallBackFetchDuplicated implements DSCallback {
		public void execute(DSResponse response, Object rawData,
				DSRequest request) {

			if (response.getStatus() == RPCResponse.STATUS_SUCCESS) {
				if (response.getTotalRows() >0) {
					if (listener != null) {
						listener.handleFetchDuplicatedDataOperation(true);
					}
				}
				else
				{					
					if (listener != null) {
						listener.handleFetchDuplicatedDataOperation(false);
					}
				}
			}
		}
	}


	public ServicoOperacoesCRUD(DynamicForm formulario) {
		this.formulario = formulario;
	}

	public ServicoOperacoesCRUD(String operationID, DynamicForm formulario) {
		this.operationID = operationID;
		this.formulario = formulario;
	}

	public void salva() {
		if (this.formulario != null) {
			this.formulario.saveData(new CallBackSalvar(),
					getRequestProperties());
		}
	}

	public void atualiza() {
		if (this.formulario != null) {
			this.formulario.saveData(new CallBackSalvar(),
					getRequestProperties());

		}
	}

	public void fetch(String name, int value) {
		if (this.formulario != null) {
			this.formulario.fetchData(
					new Criteria(name, String.valueOf(value)),
					new CallBackFetch());
		}
	}

	public void apaga(String name, int value) {
		Record r = new Record();
		r.setAttribute(name, String.valueOf(value));
		DataSource ds = DataSource.get(nomeDataSouce);
		ds.removeData(r, new CallBackApagar());
	}

	private DSRequest getRequestProperties() {
		DSRequest request = this.getDSRequest();
		if (this.operationID != null) {
			request.setOperationId(operationID);
		}
		return request;
	}

	private DSRequest getDSRequest() {
		return  new DSRequest();
	}

	public String getTituloMensagem() {
		return tituloMensagem;
	}

	public void setTituloMensagem(String tituloMensagem) {
		this.tituloMensagem = tituloMensagem;
	}

	public String getMensagem() {
		return mensagem;
	}

	public void setMensagem(String mensagem) {
		this.mensagem = mensagem;
	}

	public void setNomeDataSource(String nomeDataSource) {
		nomeDataSouce = nomeDataSource;
	}

	public void verificaCamposDuplicados(String operationId, Map<String, String> campos) {
		Criteria criteria = new Criteria();

		// Percorre os campos do mapa
		Iterator<Entry<String, String>> it = campos.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String> pairs = it.next();
			criteria.addCriteria(pairs.getKey(), pairs.getValue());
			it.remove(); // avoids a ConcurrentModificationException
		}

		DSRequest req = new DSRequest();
		req.setOperationId(operationId);

		ListGrid pesquisaDuplicidade = new ListGrid();
		pesquisaDuplicidade.setDataSource(formulario.getDataSource());
		pesquisaDuplicidade.fetchData(criteria, new CallBackFetchDuplicated(), req);
	}

	public void registerListener(EventosOperacoesHandler listener) {
		this.listener = listener;	
	}
}
